ModalDialog
ModalDialog Begin user interaction in a modal dialog
#include <Dialogs.h> Dialog Manager
void ModalDialog( filterProc, itemHit );
ProcPtr filterProc ; address of custom event filter; NIL= standard
short *itemHit ; receives number of selected item
ModalDialog begins a session of user interaction with a modal dialog
(assumed to be the frontmost, active window). Control returns when the user
selects an item or types a character into a text box.
filterProc is the address of a pascal-type procedure that will have access to
each event that occurs while the dialog is active. This lets you
examine and/or modify events before the Dialog Manager sees them.
If filterProc = NIL, then the standard filtering is performed - a
press of Return or Enter is converted into a mouse click of item
number 1. All other events are handled without modification.
itemHit is the address of a 16-bit integer variable. Upon return, it will
contain the number of the item selected (or, in the case of a
keystroke, the number of the appropriate editText item).
Returns: none

Notes: ModalDialog assumes that the frontmost active window is a modal dialog
window. It handles all mouse, keystroke, and window update events. It
retains control until one of the following happens:
The user selects an enabled control (the control is tracked automatically).
On return, itemHit is set to that control.
The user types a character and an enabled editText item exists in the
dialog. On return, itemHit is set to that text item.
The user presses Return or Enter. Upon return, itemHit is set to the
default item (item number 1). Note: This happens when using the
standard filtering is used; i.e., filterProc =NIL on entry.
Thus, a typical usage is in a loop, taking action until a Cancel or OK button
is clicked:
short itemHit;
myDlg = GetNewDialog( MYDLG_ID, 0, (WindowPtr) -1);
do {
ModalDialog( 0, &itemHit );
switch ( itemHit ) {
case 3: /*... handle a hit on item 3 ... */
case 4: /* ... handle a hit on item 4 ... */
/* ... etc ... */
}
} while ( (itemHit != ok) && (itemHit != cancel) );
/* ...take appropriate action for OK and Cancel buttons... */
DisposDialog( myDlg);
Note: The DialogMgr.h header file defines OK=1 and Cancel=2 (the first and
second items in the dialog; a good convention to follow).
Custom Event Filters
A custom filter lets you examine and/or modify events as they occur while
executing a modal dialog. For instance, this lets you convert a press of the
Esc key into a click of the Cancel button. Another use is in processing
command-shifted keystrokes cmd-C, cmd-V, and cmd-X to implement
cut-and-paste in editText items.
The format of filterProc is as follows:
pascal Boolean myDlgFilter( DialogPtr theDlg, EventRecord
* theEvent, short *itemHit )
/* theDlg = ptr to relevant dialog window */
/* theEvent = addr of EventRecord to filter */
/* itemHit = addr to receive item number */
{
/* Check the EventRecord and modify theDlg and itemHit
as appropriate. Return:
TRUE to indicate you've handled it completely
FALSE to request the Dialog Manager to finish handling
*/
return( TRUE ); [TOKEN:12074] or FALSE to pass it on */
}
The filterProc return value could be called doneFlag . When you get an
event that you handle completely, return TRUE. If you want the Dialog
Manager to process the event, return FALSE. The action taken when you
return FALSE (or when filterProc =NIL) is as follows:
Activate and update events are handled by the Dialog Manager.
For mouseDown events in an enabled control, TrackControl is called and
if the mouse is released inside the control, its item number is returned in
itemHit .
For mouseDown events in an enabled editText item: the I-Beam cursor is
displayed or the selected text is highlighted.
For keyDown events: if an enabled editText item exists, the character is
drawn and the item number is returned in itemHit. Note: command-shift
is ignored and must be handled through a filter.
Notes: It is OK for a filterProc to modify fields of the event record (e.g.,
to convert one type of event to an other) and then return FALSE, letting the
Dialog Manager handle it. To discard an event, set EventRecord->what to
nullEvent. Disk-insert events are masked from your input, but you can
test for them in the filter via GetNextEvent with an eventMask of
diskMask.
In the following example, the filterProc handles Enter and Esc, but lets all
other events occur naturally. This example also shows the standard way to
handle radio controls (turn all off, then turn the selected one back on) and a
simple way to frame the default item (always item 1 in a modal dialog); i.e.,
the item that will be assumed if the user presses Return.
Example
#include <Dialogs.h>
#include <Events.h>
short itemHit, j;
ControlHandle iHndl; // these three are used in GetDItem
Rect iRect;
short iType;
// Prototypes
pascal Boolean MyDlgFilter(DialogPtr, EventRecord *, short *);
pascal void MyItemProc(WindowPtr, short);
myDlg = GetNewDialog(MYDLG_ID,0,(WindowPtr)-1L);
/*
Assume dialog items 3, 4, and 5 are radio buttons.
Item 7 is a "dummy" user item for outlining the OK button.
The following lines set up so that item #1 will be framed.
*/
GetDItem( myDlg, 7, &iType, &iHndl, &iRect );
SetDItem( myDlg, 7, iType, MyItemProc, &iRect );
ShowWindow( myDlg ); // display with OK button framed
// ===== loop to handle the dialog =====
do {
ModalDialog( MyDlgFilter, &itemHit );
switch ( itemHit ) {
case 3:
case 4:
case 5:
for ( j=3; j<=5; j++ ) { // turn off all radio buttons
GetDItem( myDlg, j, &iType, &iHndl, &iRect);
SetCtlValue( iHndl, 0 );
} // now, turn on the selected one
GetDItem( myDlg, itemHit, &iType, &iHndl, &iRect);
SetCtlValue( iHndl, 1 );
break;
}
} while ( (itemHit != ok) && (itemHit != cancel) );
DisposDialog( myDlg);
// ================= the event filter proc ==================
pascal Boolean MyDlgFilter(DialogPtr theDlg,EventRecord * theEvent,
short *itemHit )
{
if ( theEvent->what != keyDown ) // just looking for keystrokes
return(FALSE);
switch ( ( theEvent-> message) & charCodeMask ) {
case 0x0d: // Return pressed or ...
case 0x03: // ... Enter pressed
*itemHit = ok;
return( TRUE ); // Note: pascal-style TRUE
case 0x1b:
*itemHit = cancel; // Esc pressed
return( TRUE );
default:
return( FALSE ); // all others
}
}
// =========== this routine frames dialog item #1 =============
pascal void MyItemProc(WindowPtr theDlg, short theItem )
{
Rect iRect;
Handle iHndl;
short iType;
GetDItem (theDlg, 1, &iType, &iHndl, &iRect ); // item #1
PenSize( 3,3 );
InsetRect( &iRect, -4,-4);
FrameRoundRect( &iRect, 16,16 );
}